home *** CD-ROM | disk | FTP | other *** search
- Subject: v17i076: Usenix/IEEE POSIX replacement for TAR and CPIO, Part03/06
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Mark H. Colburn <mark@jhereg.jhereg.mn.org>
- Posting-number: Volume 17, Issue 76
- Archive-name: pax/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 6)."
- # Contents: fileio.c namelist.c pax.c pax.h tar.c
- # Wrapped by mark@jhereg on Tue Dec 27 19:37:45 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f fileio.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"fileio.c\"
- else
- echo shar: Extracting \"fileio.c\" \(10596 characters\)
- sed "s/^X//" >fileio.c <<'END_OF_fileio.c'
- X/* $Source: /u/mark/src/pax/RCS/fileio.c,v $
- X *
- X * $Revision: 1.1 $
- X *
- X * fileio.c - file I/O functions for all archive interfaces
- X *
- X * DESCRIPTION
- X *
- X * These function all do I/O of some form or another. They are
- X * grouped here mainly for convienence.
- X *
- X * AUTHOR
- X *
- X * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- X *
- X * Sponsored by The USENIX Association for public distribution.
- X *
- X * Copyright (c) 1989 Mark H. Colburn.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in all such
- X * forms and that any documentation, advertising materials, and other
- X * materials related to such distribution and use acknowledge that the
- X * software was developed * by Mark H. Colburn and sponsored by The
- X * USENIX Association.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * $Log: fileio.c,v $
- X * Revision 1.1 88/12/23 18:02:09 mark
- X * Initial revision
- X *
- X */
- X
- X#ifndef lint
- Xstatic char *ident = "$Id: fileio.c,v 1.1 88/12/23 18:02:09 mark Rel $";
- Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- X#endif /* ! lint */
- X
- X
- X/* Headers */
- X
- X#include "pax.h"
- X
- X
- X/* open_archive - open an archive file.
- X *
- X * DESCRIPTION
- X *
- X * Open_archive will open an archive file for reading or writing,
- X * setting the proper file mode, depending on the "mode" passed to
- X * it. All buffer pointers are reset according to the mode
- X * specified.
- X *
- X * PARAMETERS
- X *
- X * int mode - specifies whether we are reading or writing.
- X *
- X * RETURNS
- X *
- X * Returns a zero if successfull, or -1 if an error occured during
- X * the open.
- X */
- X
- X#ifdef __STDC__
- X
- Xint open_archive(int mode)
- X
- X#else
- X
- Xint open_archive(mode)
- Xint mode;
- X
- X#endif
- X{
- X if (ar_file[0] == '-' && ar_file[1] == '\0') {
- X if (mode == AR_READ) {
- X archivefd = STDIN;
- X bufend = bufidx = bufstart;
- X } else {
- X archivefd = STDOUT;
- X }
- X } else if (mode == AR_READ) {
- X archivefd = open(ar_file, O_RDONLY | O_BINARY);
- X bufend = bufidx = bufstart; /* set up for initial read */
- X } else if (mode == AR_WRITE) {
- X archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
- X } else if (mode == AR_APPEND) {
- X archivefd = open(ar_file, O_RDWR | O_BINARY, 0666);
- X bufend = bufidx = bufstart; /* set up for initial read */
- X }
- X
- X if (archivefd < 0) {
- X warnarch(syserr(), (OFFSET) 0);
- X return (-1);
- X }
- X ++arvolume;
- X return (0);
- X}
- X
- X
- X/* close_archive - close the archive file
- X *
- X * DESCRIPTION
- X *
- X * Closes the current archive and resets the archive end of file
- X * marker.
- X */
- X
- X#ifdef __STDC__
- X
- Xvoid close_archive(void)
- X
- X#else
- X
- Xvoid close_archive()
- X
- X#endif
- X{
- X if (archivefd != STDIN && archivefd != STDOUT) {
- X close(archivefd);
- X }
- X areof = 0;
- X}
- X
- X
- X/* openo - open an output file
- X *
- X * DESCRIPTION
- X *
- X * Openo opens the named file for output. The file mode and type are
- X * set based on the values stored in the stat structure for the file.
- X * If the file is a special file, then no data will be written, the
- X * file/directory/Fifo, etc., will just be created. Appropriate
- X * permission may be required to create special files.
- X *
- X * PARAMETERS
- X *
- X * char *name - The name of the file to create
- X * Stat *asb - Stat structure for the file
- X * Link *linkp; - pointer to link chain for this file
- X * int ispass - true if we are operating in "pass" mode
- X *
- X * RETURNS
- X *
- X * Returns the output file descriptor, 0 if no data is required or -1
- X * if unsuccessful. Note that UNIX open() will never return 0 because
- X * the standard input is in use.
- X */
- X
- X#ifdef __STDC__
- X
- Xint openo(char *name, Stat *asb, Link *linkp, int ispass)
- X
- X#else
- X
- Xint openo(name, asb, linkp, ispass)
- Xchar *name;
- XStat *asb;
- XLink *linkp;
- Xint ispass;
- X
- X#endif
- X{
- X int exists;
- X int fd;
- X ushort perm;
- X ushort operm = 0;
- X Stat osb;
- X#ifdef S_IFLNK
- X int ssize;
- X char sname[PATH_MAX + 1];
- X#endif /* S_IFLNK */
- X
- X if (exists = (LSTAT(name, &osb) == 0)) {
- X if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
- X warn(name, "Same file");
- X return (-1);
- X } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
- X operm = osb.sb_mode & S_IPERM;
- X } else if (REMOVE(name, &osb) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else {
- X exists = 0;
- X }
- X }
- X if (linkp) {
- X if (exists) {
- X if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
- X return (0);
- X } else if (unlink(name) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else {
- X exists = 0;
- X }
- X }
- X if (link(linkp->l_name, name) != 0) {
- X if (errno == ENOENT) {
- X if (f_create_dirs) {
- X if (dirneed(name) != 0 ||
- X link(linkp->l_name, name) != 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X warn(name,
- X "Directories are not being created (-d option)");
- X }
- X return(0);
- X } else if (errno != EXDEV) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X return(0);
- X }
- X }
- X perm = asb->sb_mode & S_IPERM;
- X switch (asb->sb_mode & S_IFMT) {
- X case S_IFBLK:
- X case S_IFCHR:
- X fd = 0;
- X if (exists) {
- X if (asb->sb_rdev == osb.sb_rdev) {
- X if (perm != operm && chmod(name, (int) perm) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else {
- X break;
- X }
- X } else if (REMOVE(name, &osb) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else {
- X exists = 0;
- X }
- X }
- X if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
- X if (errno == ENOENT) {
- X if (f_create_dirs) {
- X if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode,
- X (int) asb->sb_rdev) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X warn(name, "Directories are not being created (-d option)");
- X }
- X } else {
- X warn(name, syserr());
- X return (-1);
- X }
- X }
- X return(0);
- X break;
- X case S_IFDIR:
- X if (exists) {
- X if (perm != operm && chmod(name, (int) perm) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else if (f_create_dirs) {
- X if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X warn(name, "Directories are not being created (-d option)");
- X }
- X return (0);
- X#ifdef S_IFIFO
- X case S_IFIFO:
- X fd = 0;
- X if (exists) {
- X if (perm != operm && chmod(name, (int) perm) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
- X if (errno == ENOENT) {
- X if (f_create_dirs) {
- X if (dirneed(name) < 0
- X || mknod(name, (int) asb->sb_mode, 0) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X warn(name, "Directories are not being created (-d option)");
- X }
- X } else {
- X warn(name, syserr());
- X return (-1);
- X }
- X }
- X return(0);
- X break;
- X#endif /* S_IFIFO */
- X#ifdef S_IFLNK
- X case S_IFLNK:
- X if (exists) {
- X if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
- X return (0);
- X } else if (REMOVE(name, &osb) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else {
- X exists = 0;
- X }
- X }
- X if (symlink(asb->sb_link, name) < 0) {
- X if (errno == ENOENT) {
- X if (f_create_dirs) {
- X if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X warn(name, "Directories are not being created (-d option)");
- X }
- X } else {
- X warn(name, syserr());
- X return (-1);
- X }
- X }
- X return (0); /* Can't chown()/chmod() a symbolic link */
- X#endif /* S_IFLNK */
- X case S_IFREG:
- X if (exists) {
- X if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
- X warn(name, "Newer file exists");
- X return (-1);
- X } else if (unlink(name) < 0) {
- X warn(name, syserr());
- X return (-1);
- X } else {
- X exists = 0;
- X }
- X }
- X if ((fd = creat(name, (int) perm)) < 0) {
- X if (errno == ENOENT) {
- X if (f_create_dirs) {
- X if (dirneed(name) < 0 ||
- X (fd = creat(name, (int) perm)) < 0) {
- X warn(name, syserr());
- X return (-1);
- X }
- X } else {
- X /*
- X * the file requires a directory which does not exist
- X * and which the user does not want created, so skip
- X * the file...
- X */
- X warn(name, "Directories are not being created (-d option)");
- X return(0);
- X }
- X } else {
- X warn(name, syserr());
- X return (-1);
- X }
- X }
- X break;
- X default:
- X warn(name, "Unknown filetype");
- X return (-1);
- X }
- X if (f_owner) {
- X if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
- X chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
- X }
- X }
- X return (fd);
- X}
- X
- X
- X/* openi - open the next input file
- X *
- X * DESCRIPTION
- X *
- X * Openi will attempt to open the next file for input. If the file is
- X * a special file, such as a directory, FIFO, link, character- or
- X * block-special file, then the file size field of the stat structure
- X * is zeroed to make sure that no data is written out for the file.
- X * If the file is a special file, then a file descriptor of 0 is
- X * returned to the caller, which is handled specially. If the file
- X * is a regular file, then the file is opened and a file descriptor
- X * to the open file is returned to the caller.
- X *
- X * PARAMETERS
- X *
- X * char *name - pointer to the name of the file to open
- X * Stat *asb - pointer to the stat block for the file to open
- X *
- X * RETURNS
- X *
- X * Returns a file descriptor, 0 if no data exists, or -1 at EOF. This
- X * kludge works because standard input is in use, preventing open() from
- X * returning zero.
- X */
- X
- X#ifdef __STDC__
- X
- Xint openi(char *name, Stat *asb)
- X
- X#else
- X
- Xint openi(name, asb)
- Xchar *name; /* name of file to open */
- XStat *asb; /* pointer to stat structure for file */
- X
- X#endif
- X{
- X int fd;
- X
- X switch (asb->sb_mode & S_IFMT) {
- X case S_IFDIR:
- X asb->sb_nlink = 1;
- X asb->sb_size = 0;
- X return (0);
- X#ifdef S_IFLNK
- X case S_IFLNK:
- X if ((asb->sb_size = readlink(name,
- X asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
- X warn(name, syserr());
- X return(0);
- X }
- X asb->sb_link[asb->sb_size] = '\0';
- X return (0);
- X#endif /* S_IFLNK */
- X case S_IFREG:
- X if (asb->sb_size == 0) {
- X return (0);
- X }
- X if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
- X warn(name, syserr());
- X }
- X return (fd);
- X default:
- X asb->sb_size = 0;
- X return (0);
- X }
- X}
- END_OF_fileio.c
- if test 10596 -ne `wc -c <fileio.c`; then
- echo shar: \"fileio.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f namelist.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"namelist.c\"
- else
- echo shar: Extracting \"namelist.c\" \(11056 characters\)
- sed "s/^X//" >namelist.c <<'END_OF_namelist.c'
- X/* $Source: /u/mark/src/pax/RCS/namelist.c,v $
- X *
- X * $Revision: 1.1 $
- X *
- X * namelist.c - track filenames given as arguments to tar/cpio/pax
- X *
- X * DESCRIPTION
- X *
- X * Arguments may be regular expressions, therefore all agurments will
- X * be treated as if they were regular expressions, even if they are
- X * not.
- X *
- X * AUTHOR
- X *
- X * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- X *
- X * Sponsored by The USENIX Association for public distribution.
- X *
- X * Copyright (c) 1989 Mark H. Colburn.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in all such
- X * forms and that any documentation, advertising materials, and other
- X * materials related to such distribution and use acknowledge that the
- X * software was developed * by Mark H. Colburn and sponsored by The
- X * USENIX Association.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * $Log: namelist.c,v $
- X * Revision 1.1 88/12/23 18:02:17 mark
- X * Initial revision
- X *
- X */
- X
- X#ifndef lint
- Xstatic char *ident = "$Id: namelist.c,v 1.1 88/12/23 18:02:17 mark Rel $";
- Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- X#endif /* ! lint */
- X
- X
- X/* Headers */
- X
- X#include "pax.h"
- X
- X
- X/* Type Definitions */
- X
- X/*
- X * Structure for keeping track of filenames and lists thereof.
- X */
- Xstruct nm_list {
- X struct nm_list *next;
- X short length; /* cached strlen(name) */
- X char found; /* A matching file has been found */
- X char firstch; /* First char is literally matched */
- X char regexp; /* regexp pattern for item */
- X char name[1]; /* name of file or rexexp */
- X};
- X
- Xstruct dirinfo {
- X char dirname[PATH_MAX + 1]; /* name of directory */
- X OFFSET where; /* current location in directory */
- X struct dirinfo *next;
- X};
- X
- X
- X/* Function Prototypes */
- X
- X#ifndef __STDC__
- X
- Xstatic void pushdir();
- Xstatic struct dirinfo *popdir();
- X
- X#else
- X
- Xstatic void pushdir(struct dirinfo *info);
- Xstatic struct dirinfo *popdir(void);
- X
- X#endif
- X
- X
- X/* Internal Identifiers */
- X
- Xstatic struct nm_list *namelast; /* Points to last name in list */
- Xstatic struct nm_list *namelist; /* Points to first name in list */
- X
- X
- X/* addname - add a name to the namelist.
- X *
- X * DESCRIPTION
- X *
- X * Addname adds the name given to the name list. Memory for the
- X * namelist structure is dynamically allocated. If the space for
- X * the structure cannot be allocated, then the program will exit
- X * the an out of memory error message and a non-zero return code
- X * will be returned to the caller.
- X *
- X * PARAMETERS
- X *
- X * char *name - A pointer to the name to add to the list
- X */
- X
- X#ifdef __STDC__
- X
- Xvoid add_name(char *name)
- X
- X#else
- X
- Xvoid add_name(name)
- Xchar *name; /* pointer to name */
- X
- X#endif
- X{
- X int i; /* Length of string */
- X struct nm_list *p; /* Current struct pointer */
- X
- X i = strlen(name);
- X p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
- X if (!p) {
- X fatal("cannot allocate memory for namelist entry\n");
- X }
- X p->next = (struct nm_list *) NULL;
- X p->length = i;
- X strncpy(p->name, name, i);
- X p->name[i] = '\0'; /* Null term */
- X p->found = 0;
- X p->firstch = isalpha(name[0]);
- X if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
- X p->regexp = 1;
- X }
- X if (namelast) {
- X namelast->next = p;
- X }
- X namelast = p;
- X if (!namelist) {
- X namelist = p;
- X }
- X}
- X
- X
- X/* name_match - match a name from an archive with a name from the namelist
- X *
- X * DESCRIPTION
- X *
- X * Name_match attempts to find a name pointed at by p in the namelist.
- X * If no namelist is available, then all filenames passed in are
- X * assumed to match the filename criteria. Name_match knows how to
- X * match names with regular expressions, etc.
- X *
- X * PARAMETERS
- X *
- X * char *p - the name to match
- X *
- X * RETURNS
- X *
- X * Returns 1 if the name is in the namelist, or no name list is
- X * available, otherwise returns 0
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xint name_match(char *p)
- X
- X#else
- X
- Xint name_match(p)
- Xchar *p;
- X
- X#endif
- X{
- X struct nm_list *nlp;
- X int len;
- X
- X if ((nlp = namelist) == 0) {/* Empty namelist is easy */
- X return (1);
- X }
- X len = strlen(p);
- X for (; nlp != 0; nlp = nlp->next) {
- X /* If first chars don't match, quick skip */
- X if (nlp->firstch && nlp->name[0] != p[0]) {
- X continue;
- X }
- X /* Regular expressions */
- X if (nlp->regexp) {
- X if (wildmat(nlp->name, p)) {
- X nlp->found = 1; /* Remember it matched */
- X return (1); /* We got a match */
- X }
- X continue;
- X }
- X /* Plain Old Strings */
- X if (nlp->length <= len /* Archive len >= specified */
- X && (p[nlp->length] == '\0' || p[nlp->length] == '/')
- X && strncmp(p, nlp->name, nlp->length) == 0) {
- X /* Name compare */
- X nlp->found = 1; /* Remember it matched */
- X return (1); /* We got a match */
- X }
- X }
- X return (0);
- X}
- X
- X
- X/* names_notfound - print names of files in namelist that were not found
- X *
- X * DESCRIPTION
- X *
- X * Names_notfound scans through the namelist for any files which were
- X * named, but for which a matching file was not processed by the
- X * archive. Each of the files is listed on the standard error.
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xvoid names_notfound(void)
- X
- X#else
- X
- Xvoid names_notfound()
- X
- X#endif
- X{
- X struct nm_list *nlp;
- X
- X for (nlp = namelist; nlp != 0; nlp = nlp->next) {
- X if (!nlp->found) {
- X fprintf(stderr, "%s: %s not found in archive\n",
- X myname, nlp->name);
- X }
- X free(nlp);
- X }
- X namelist = (struct nm_list *) NULL;
- X namelast = (struct nm_list *) NULL;
- X}
- X
- X
- X/* name_init - set up to gather file names
- X *
- X * DESCRIPTION
- X *
- X * Name_init sets up the namelist pointers so that we may access the
- X * command line arguments. At least the first item of the command
- X * line (argv[0]) is assumed to be stripped off, prior to the
- X * name_init call.
- X *
- X * PARAMETERS
- X *
- X * int argc - number of items in argc
- X * char **argv - pointer to the command line arguments
- X */
- X
- X#ifdef __STDC__
- X
- Xvoid name_init(int argc, char **argv)
- X
- X#else
- X
- Xvoid name_init(argc, argv)
- Xint argc;
- Xchar **argv;
- X
- X#endif
- X{
- X /* Get file names from argv, after options. */
- X n_argc = argc;
- X n_argv = argv;
- X}
- X
- X
- X/* name_next - get the next name from argv or the name file.
- X *
- X * DESCRIPTION
- X *
- X * Name next finds the next name which is to be processed in the
- X * archive. If the named file is a directory, then the directory
- X * is recursively traversed for additional file names. Directory
- X * names and locations within the directory are kept track of by
- X * using a directory stack. See the pushdir/popdir function for
- X * more details.
- X *
- X * The names come from argv, after options or from the standard input.
- X *
- X * PARAMETERS
- X *
- X * name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
- X * statbuf - a pointer to a stat structure
- X *
- X * RETURNS
- X *
- X * Returns -1 if there are no names left, (e.g. EOF), otherwise returns
- X * 0
- X */
- X
- X#ifdef __STDC__
- X
- Xint name_next(char *name, Stat *statbuf)
- X
- X#else
- X
- Xint name_next(name, statbuf)
- Xchar *name;
- XStat *statbuf;
- X
- X#endif
- X{
- X int err = -1;
- X static int in_subdir = 0;
- X static DIR *dirp;
- X struct dirent *d;
- X static struct dirinfo *curr_dir;
- X int len;
- X
- X do {
- X if (names_from_stdin) {
- X if (lineget(stdin, name) < 0) {
- X return (-1);
- X }
- X if (nameopt(name) < 0) {
- X continue;
- X }
- X } else {
- X if (in_subdir) {
- X if ((d = readdir(dirp)) != NULL) {
- X /* Skip . and .. */
- X if (strcmp(d->d_name, ".") == 0 ||
- X strcmp(d->d_name, "..") == 0) {
- X continue;
- X }
- X if (strlen(d->d_name) +
- X strlen(curr_dir->dirname) >= PATH_MAX) {
- X warn("name too long", d->d_name);
- X continue;
- X }
- X strcpy(name, curr_dir->dirname);
- X strcat(name, d->d_name);
- X } else {
- X closedir(dirp);
- X in_subdir--;
- X curr_dir = popdir();
- X if (in_subdir) {
- X errno = 0;
- X if ((dirp = opendir(curr_dir->dirname)) == NULL) {
- X warn(curr_dir->dirname, "error opening directory (1)");
- X in_subdir--;
- X }
- X seekdir(dirp, curr_dir->where);
- X }
- X continue;
- X }
- X } else if (optind >= n_argc) {
- X return (-1);
- X } else {
- X strcpy(name, n_argv[optind++]);
- X }
- X }
- X if ((err = LSTAT(name, statbuf)) < 0) {
- X warn(name, syserr());
- X continue;
- X }
- X if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
- X if (in_subdir) {
- X curr_dir->where = telldir(dirp);
- X pushdir(curr_dir);
- X close(dirp);
- X }
- X in_subdir++;
- X
- X /* Build new prototype name */
- X if ((curr_dir = (struct dirinfo *)
- X mem_get(sizeof(struct dirinfo))) == NULL) {
- X exit(2);
- X }
- X strcpy(curr_dir->dirname, name);
- X len = strlen(curr_dir->dirname);
- X while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
- X len--; /* Delete trailing slashes */
- X }
- X curr_dir->dirname[len++] = '/'; /* Now add exactly one back */
- X curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
- X
- X errno = 0;
- X if ((dirp = opendir(curr_dir->dirname)) == NULL) {
- X warn(curr_dir->dirname, "error opening directory (2)");
- X }
- X }
- X } while (err < 0);
- X return (0);
- X}
- X
- X
- X/* name_gather - gather names in a list for scanning.
- X *
- X * DESCRIPTION
- X *
- X * Name_gather takes names from the command line and adds them to
- X * the name list.
- X *
- X * FIXME
- X *
- X * We could hash the names if we really care about speed here.
- X */
- X
- X#ifdef __STDC__
- X
- Xvoid name_gather(void)
- X
- X#else
- X
- Xvoid name_gather()
- X
- X#endif
- X{
- X while (optind < n_argc) {
- X add_name(n_argv[optind++]);
- X }
- X}
- X
- X
- Xstatic struct dirinfo *stack_head = NULL;
- X
- X
- X/* pushdir - pushes a directory name on the directory stack
- X *
- X * DESCRIPTION
- X *
- X * The pushdir function puses the directory structure which is pointed
- X * to by "info" onto a stack for later processing. The information
- X * may be retrieved later with a call to popdir().
- X *
- X * PARAMETERS
- X *
- X * dirinfo *info - pointer to directory structure to save
- X */
- X
- X#ifdef __STDC__
- X
- Xstatic void pushdir(struct dirinfo *info)
- X
- X#else
- X
- Xstatic void pushdir(info)
- Xstruct dirinfo *info;
- X
- X#endif
- X{
- X if (stack_head == NULL) {
- X stack_head = info;
- X stack_head->next = NULL;
- X } else {
- X info->next = stack_head;
- X stack_head = info;
- X }
- X}
- X
- X
- X/* popdir - pop a directory structure off the directory stack.
- X *
- X * DESCRIPTION
- X *
- X * The popdir function pops the most recently pushed directory
- X * structure off of the directory stack and returns it to the calling
- X * function.
- X *
- X * RETURNS
- X *
- X * Returns a pointer to the most recently pushed directory structure
- X * or NULL if the stack is empty.
- X */
- X
- X#ifdef __STDC__
- X
- Xstatic struct dirinfo *popdir(void)
- X
- X#else
- X
- Xstatic struct dirinfo *popdir()
- X
- X#endif
- X{
- X struct dirinfo *tmp;
- X
- X if (stack_head == NULL) {
- X return(NULL);
- X } else {
- X tmp = stack_head;
- X stack_head = stack_head->next;
- X }
- X return(tmp);
- X}
- END_OF_namelist.c
- if test 11056 -ne `wc -c <namelist.c`; then
- echo shar: \"namelist.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f pax.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"pax.c\"
- else
- echo shar: Extracting \"pax.c\" \(13026 characters\)
- sed "s/^X//" >pax.c <<'END_OF_pax.c'
- X/* $Source: /u/mark/src/pax/RCS/pax.c,v $
- X *
- X * $Revision: 1.1 $
- X *
- X * DESCRIPTION
- X *
- X * Pax is the archiver described in IEEE P1003.2. It is an archiver
- X * which understands both tar and cpio archives and has a new interface.
- X *
- X * SYNOPSIS
- X *
- X * pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
- X * pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
- X * pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...]
- X * [-t device][-x format][pathname...]
- X * pax -r -w [-ilmopuvy][-s replstr][pathname...] directory
- X *
- X * DESCRIPTION
- X *
- X * PAX - POSIX conforming tar and cpio archive handler. This
- X * program implements POSIX conformant versions of tar, cpio and pax
- X * archive handlers for UNIX. These handlers have defined befined
- X * by the IEEE P1003.2 commitee.
- X *
- X * COMPILATION
- X *
- X * A number of different compile time configuration options are
- X * available, please see the Makefile and config.h for more details.
- X *
- X * AUTHOR
- X *
- X * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- X *
- X *
- X * Sponsored by The USENIX Association for public distribution.
- X *
- X * Copyright (c) 1989 Mark H. Colburn.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in all such
- X * forms and that any documentation, advertising materials, and other
- X * materials related to such distribution and use acknowledge that the
- X * software was developed * by Mark H. Colburn and sponsored by The
- X * USENIX Association.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * $Log: pax.c,v $
- X * Revision 1.1 88/12/23 18:02:23 mark
- X * Initial revision
- X *
- X */
- X
- X#ifndef lint
- Xstatic char *ident = "$Id: pax.c,v 1.1 88/12/23 18:02:23 mark Rel $";
- Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- X#endif /* ! lint */
- X
- X
- X/* Headers */
- X
- X#define NO_EXTERN
- X#include "pax.h"
- X
- X
- X/* Globally Available Identifiers */
- X
- Xchar *ar_file; /* File containing name of archive */
- Xchar *bufend; /* End of data within archive buffer */
- Xchar *bufstart; /* Archive buffer */
- Xchar *bufidx; /* Archive buffer index */
- Xchar *myname; /* name of executable (argv[0]) */
- Xchar **n_argv; /* Argv used by name routines */
- Xint n_argc; /* Argc used by name routines */
- Xint archivefd; /* Archive file descriptor */
- Xint blocking; /* Size of each block, in records */
- Xint gid; /* Group ID */
- Xint head_standard; /* true if archive is POSIX format */
- Xint ar_interface; /* defines interface we are using */
- Xint ar_format; /* defines current archve format */
- Xint mask; /* File creation mask */
- Xint ttyf; /* For interactive queries */
- Xint uid; /* User ID */
- Xint names_from_stdin; /* names for files are from stdin */
- XOFFSET total; /* Total number of bytes transferred */
- Xshort f_access_time; /* Reset access times of input files */
- Xshort areof; /* End of input volume reached */
- Xshort f_create_dirs; /* Create missing directories */
- Xshort f_append; /* Add named files to end of archive */
- Xshort f_create; /* create a new archive */
- Xshort f_extract; /* Extract named files from archive */
- Xshort f_follow_links; /* follow symbolic links */
- Xshort f_interactive; /* Interactivly extract files */
- Xshort f_linksleft; /* Report on unresolved links */
- Xshort f_list; /* List files on the archive */
- Xshort f_modified; /* Don't restore modification times */
- Xshort f_verbose; /* Turn on verbose mode */
- Xshort f_link; /* link files where possible */
- Xshort f_owner; /* extract files as the user */
- Xshort f_pass; /* pass files between directories */
- Xshort f_newer; /* append files to archive if newer */
- Xshort f_disposition; /* ask for file disposition */
- Xshort f_reverse_match; /* Reverse sense of pattern match */
- Xshort f_modification_time; /* Retain file modification time */
- Xshort f_unconditional; /* Copy unconditionally */
- Xtime_t now = 0; /* Current time */
- Xuint arvolume; /* Volume number */
- Xuint blocksize = BLOCKSIZE; /* Archive block size */
- XFILE *msgfile; /* message outpu file stdout/stderr */
- XReplstr *rplhead = NULL; /* pointer to head of replstr list */
- XReplstr *rpltail; /* pointer to tail of replstr list */
- X
- X
- X/* Function Prototypes */
- X
- X#ifdef __STDC__
- X
- Xstatic void usage(void);
- Xstatic OFFSET pax_optsize(char *);
- X
- X#else /* !__STDC__ */
- X
- Xstatic void usage();
- Xstatic OFFSET pax_optsize();
- X
- X#endif /* __STDC__ */
- X
- X
- X/* main - main routine for handling all archive formats.
- X *
- X * DESCRIPTION
- X *
- X * Set up globals and call the proper interface as specified by the user.
- X *
- X * PARAMETERS
- X *
- X * int argc - count of user supplied arguments
- X * char **argv - user supplied arguments
- X *
- X * RETURNS
- X *
- X * Returns an exit code of 0 to the parent process.
- X */
- X
- X#ifdef __STDC__
- X
- Xint main(int argc, char **argv)
- X
- X#else
- X
- Xint main(argc, argv)
- Xint argc;
- Xchar **argv;
- X
- X#endif
- X{
- X /* strip the pathname off of the name of the executable */
- X if ((myname = strrchr(argv[0], '/')) != (char *)NULL) {
- X myname++;
- X } else {
- X myname = argv[0];
- X }
- X
- X /* set upt for collecting other command line arguments */
- X name_init(argc, argv);
- X
- X /* get all our necessary information */
- X mask = umask(0);
- X uid = getuid();
- X gid = getgid();
- X now = time((time_t *) 0);
- X
- X /* open terminal for interactive queries */
- X ttyf = open_tty();
- X
- X if (strcmp(myname, "tar")==0) {
- X do_tar(argc, argv);
- X } else if (strcmp(myname, "cpio")==0) {
- X do_cpio(argc, argv);
- X } else {
- X do_pax(argc, argv);
- X }
- X exit(0);
- X /* NOTREACHED */
- X}
- X
- X
- X/* do_pax - provide a PAX conformant user interface for archive handling
- X *
- X * DESCRIPTION
- X *
- X * Process the command line parameters given, doing some minimal sanity
- X * checking, and then launch the specified archiving functions.
- X *
- X * PARAMETERS
- X *
- X * int ac - A count of arguments in av. Should be passed argc
- X * from main
- X * char **av - A pointer to an argument list. Should be passed
- X * argv from main
- X *
- X * RETURNS
- X *
- X * Normally returns 0. If an error occurs, -1 is returned
- X * and state is set to reflect the error.
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xint do_pax(int ac, char **av)
- X
- X#else
- X
- Xint do_pax(ac, av)
- Xint ac; /* argument counter */
- Xchar **av; /* arguments */
- X
- X#endif
- X{
- X int c;
- X char *dirname;
- X Stat st;
- X
- X /* default input/output file for PAX is STDIN/STDOUT */
- X ar_file = "-";
- X
- X /*
- X * set up the flags to reflect the default pax inteface. Unfortunately
- X * the pax interface has several options which are completely opposite
- X * of the tar and/or cpio interfaces...
- X */
- X f_unconditional = 1;
- X f_modification_time = 1;
- X f_create_dirs = 1;
- X f_list = 1;
- X blocksize = 0;
- X blocking = 0;
- X ar_interface = PAX;
- X ar_format = TAR; /* default interface if none given for -w */
- X msgfile=stdout;
- X
- X while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) {
- X switch (c) {
- X case 'a':
- X f_append = 1;
- X f_list = 0;
- X break;
- X case 'b':
- X if ((blocksize = pax_optsize(optarg)) == 0) {
- X fatal("Bad block size");
- X }
- X break;
- X case 'c':
- X f_reverse_match = 1;
- X break;
- X case 'd':
- X f_create_dirs = 0;
- X break;
- X case 'f':
- X if (blocksize == 0) {
- X blocking = 1;
- X blocksize = 1 * BLOCKSIZE;
- X }
- X ar_file = optarg;
- X break;
- X case 'i':
- X f_interactive = 1;
- X break;
- X case 'l':
- X f_link = 1;
- X break;
- X case 'm':
- X f_modification_time = 0;
- X break;
- X case 'o':
- X f_owner = 1;
- X break;
- X case 'p':
- X f_access_time = 1;
- X break;
- X case 'r':
- X if (f_create) {
- X f_create = 0;
- X f_pass = 1;
- X } else {
- X f_list = 0;
- X f_extract = 1;
- X }
- X msgfile=stderr;
- X break;
- X case 's':
- X add_replstr(optarg);
- X break;
- X case 't':
- X if (blocksize == 0) {
- X blocking = 1;
- X blocksize = 10 * BLOCKSIZE;
- X }
- X ar_file = optarg;
- X break;
- X case 'u':
- X f_unconditional = 1;
- X break;
- X case 'v':
- X f_verbose = 1;
- X break;
- X case 'w':
- X if (f_extract) {
- X f_extract = 0;
- X f_pass = 1;
- X } else {
- X f_list = 0;
- X f_create = 1;
- X }
- X msgfile=stderr;
- X break;
- X case 'x':
- X if (strcmp(optarg, "ustar") == 0) {
- X ar_format = TAR;
- X } else if (strcmp(optarg, "cpio") == 0) {
- X ar_format = CPIO;
- X } else {
- X usage();
- X }
- X break;
- X case 'y':
- X f_disposition = 1;
- X break;
- X default:
- X usage();
- X }
- X }
- X
- X if (blocksize == 0) {
- X blocking = 1;
- X blocksize = blocking * BLOCKSIZE;
- X }
- X buf_allocate((OFFSET) blocksize);
- X
- X if (f_extract || f_list) {
- X open_archive(AR_READ);
- X get_archive_type();
- X read_archive();
- X } else if (f_create) {
- X if (optind >= n_argc) {
- X names_from_stdin++; /* args from stdin */
- X }
- X open_archive(AR_WRITE);
- X create_archive();
- X } else if (f_append) {
- X open_archive(AR_APPEND);
- X get_archive_type();
- X append_archive();
- X } else if (f_pass && optind < n_argc) {
- X dirname = n_argv[--n_argc];
- X if (LSTAT(dirname, &st) < 0) {
- X fatal(syserr());
- X }
- X if ((st.sb_mode & S_IFMT) != S_IFDIR) {
- X fatal("Not a directory");
- X }
- X if (optind >= n_argc) {
- X names_from_stdin++; /* args from stdin */
- X }
- X pass(dirname);
- X } else {
- X usage();
- X }
- X
- X return (0);
- X}
- X
- X
- X/* get_archive_type - determine input archive type from archive header
- X *
- X * DESCRIPTION
- X *
- X * reads the first block of the archive and determines the archive
- X * type from the data. If the archive type cannot be determined,
- X * processing stops, and a 1 is returned to the caller. If verbose
- X * mode is on, then the archive type will be printed on the standard
- X * error device as it is determined.
- X *
- X * FIXME
- X *
- X * be able to understand TAR and CPIO magic numbers
- X */
- X
- X#ifdef __STDC__
- X
- Xvoid get_archive_type(void)
- X
- X#else
- X
- Xvoid get_archive_type()
- X
- X#endif
- X{
- X if (ar_read() != 0) {
- X fatal("Unable to determine archive type.");
- X }
- X if (strncmp(bufstart, "070707", 6) == 0) {
- X ar_format = CPIO;
- X if (f_verbose) {
- X fputs("CPIO format archive\n", stderr);
- X }
- X } else if (strncmp(&bufstart[257], "ustar", 5) == 0) {
- X ar_format = TAR;
- X if (f_verbose) {
- X fputs("USTAR format archive\n", stderr);
- X }
- X } else {
- X ar_format = TAR;
- X }
- X}
- X
- X
- X/* pax_optsize - interpret a size argument
- X *
- X * DESCRIPTION
- X *
- X * Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes.
- X * Also handles simple expressions containing '+' for addition.
- X *
- X * PARAMETERS
- X *
- X * char *str - A pointer to the string to interpret
- X *
- X * RETURNS
- X *
- X * Normally returns the value represented by the expression in the
- X * the string.
- X *
- X * ERRORS
- X *
- X * If the string cannot be interpretted, the program will fail, since
- X * the buffering will be incorrect.
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xstatic OFFSET pax_optsize(char *str)
- X
- X#else
- X
- Xstatic OFFSET pax_optsize(str)
- Xchar *str; /* pointer to string to interpret */
- X
- X#endif
- X{
- X char *idx;
- X OFFSET number; /* temporary storage for current number */
- X OFFSET result; /* cumulative total to be returned to caller */
- X
- X result = 0;
- X idx = str;
- X for (;;) {
- X number = 0;
- X while (*idx >= '0' && *idx <= '9')
- X number = number * 10 + *idx++ - '0';
- X switch (*idx++) {
- X case 'b':
- X result += number * 512;
- X continue;
- X case 'k':
- X result += number * 1024;
- X continue;
- X case 'm':
- X result += number * 1024 * 1024;
- X continue;
- X case '+':
- X result += number;
- X continue;
- X case '\0':
- X result += number;
- X break;
- X default:
- X break;
- X }
- X break;
- X }
- X if (*--idx) {
- X fatal("Unrecognizable value");
- X }
- X return (result);
- X}
- X
- X
- X/* usage - print a helpful message and exit
- X *
- X * DESCRIPTION
- X *
- X * Usage prints out the usage message for the PAX interface and then
- X * exits with a non-zero termination status. This is used when a user
- X * has provided non-existant or incompatible command line arguments.
- X *
- X * RETURNS
- X *
- X * Returns an exit status of 1 to the parent process.
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xstatic void usage(void)
- X
- X#else
- X
- Xstatic void usage()
- X
- X#endif
- X{
- X fprintf(stderr, "\
- XUsage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
- X myname);
- X fprintf(stderr, "\
- X %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
- X myname);
- X fprintf(stderr, "\
- X %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n\
- X [-t device] [-x format] [pathname...]\n",
- X myname);
- X fprintf(stderr, "\
- X %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n",
- X myname);
- X exit(1);
- X}
- END_OF_pax.c
- if test 13026 -ne `wc -c <pax.c`; then
- echo shar: \"pax.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f pax.h -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"pax.h\"
- else
- echo shar: Extracting \"pax.h\" \(9317 characters\)
- sed "s/^X//" >pax.h <<'END_OF_pax.h'
- X/* $Source: /u/mark/src/pax/RCS/pax.h,v $
- X *
- X * $Revision: 1.1 $
- X *
- X * pax.h - defnitions for entire program
- X *
- X * DESCRIPTION
- X *
- X * This file contains most all of the definitions required by the PAX
- X * software. This header is included in every source file.
- X *
- X * AUTHOR
- X *
- X * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- X *
- X * Sponsored by The USENIX Association for public distribution.
- X *
- X * Copyright (c) 1989 Mark H. Colburn.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by Mark H. Colburn and sponsored by The USENIX Association.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#ifndef _PAX_H
- X#define _PAX_H
- X
- X/* Headers */
- X
- X#include "config.h"
- X#include "limits.h"
- X#include <stdio.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <sys/ioctl.h>
- X#include <sys/stat.h>
- X#include "regexp.h"
- X
- X#if defined(DIRENT) || defined(_POSIX_SOURCE)
- X# ifdef PAXDIR
- X# include "paxdir.h"
- X# else
- X# include <dirent.h>
- X# endif
- X#else
- X# include <sys/dir.h>
- X# define dirent direct
- X#endif
- X
- X#ifndef major
- X# include <sys/sysmacros.h>
- X#endif /* major */
- X
- X#ifdef SYSTIME
- X# include <sys/time.h>
- X#else /* SYSTIME */
- X# include <time.h>
- X#endif /* SYSTIME */
- X
- X#ifndef V7
- X# include <fcntl.h>
- X#endif
- X
- X#ifdef XENIX
- X# include <sys/inode.h>
- X#endif
- X
- X#include <pwd.h>
- X#include <grp.h>
- X#include <sys/file.h>
- X
- X/* Defines */
- X
- X#define STDIN 0 /* Standard input file descriptor */
- X#define STDOUT 1 /* Standard output file descriptor */
- X
- X/*
- X * Open modes; there is no <fcntl.h> with v7 UNIX and other versions of
- X * UNIX may not have all of these defined...
- X */
- X
- X#ifndef O_RDONLY
- X# define O_RDONLY 0
- X#endif
- X
- X#ifndef O_WRONLY
- X# define O_WRONLY 1
- X#endif
- X
- X#ifndef O_RDWR
- X# define O_WRONLY 2
- X#endif
- X
- X#ifndef O_BINARY
- X# define O_BINARY 0
- X#endif
- X
- X#ifndef NULL
- X# define NULL 0
- X#endif
- X
- X#define TMAGIC "ustar" /* ustar and a null */
- X#define TMAGLEN 6
- X#define TVERSION "00" /* 00 and no null */
- X#define TVERSLEN 2
- X
- X/* Values used in typeflag field */
- X#define REGTYPE '0' /* Regular File */
- X#define AREGTYPE '\0' /* Regular File */
- X#define LNKTYPE '1' /* Link */
- X#define SYMTYPE '2' /* Reserved */
- X#define CHRTYPE '3' /* Character Special File */
- X#define BLKTYPE '4' /* Block Special File */
- X#define DIRTYPE '5' /* Directory */
- X#define FIFOTYPE '6' /* FIFO */
- X#define CONTTYPE '7' /* Reserved */
- X
- X#define BLOCKSIZE 512 /* all output is padded to 512 bytes */
- X#define uint unsigned int /* Not always in types.h */
- X#define ushort unsigned short /* Not always in types.h */
- X#define BLOCK 5120 /* Default archive block size */
- X#define H_COUNT 10 /* Number of items in ASCII header */
- X#define H_PRINT "%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo"
- X#define H_SCAN "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6o%11lo"
- X#define H_STRLEN 70 /* ASCII header string length */
- X#define M_ASCII "070707" /* ASCII magic number */
- X#define M_BINARY 070707 /* Binary magic number */
- X#define M_STRLEN 6 /* ASCII magic number length */
- X#define PATHELEM 256 /* Pathname element count limit */
- X#define S_IFSHF 12 /* File type shift (shb in stat.h) */
- X#define S_IPERM 07777 /* File permission bits (shb in stat.h) */
- X#define S_IPEXE 07000 /* Special execution bits (shb in stat.h) */
- X#define S_IPOPN 0777 /* Open access bits (shb in stat.h) */
- X
- X/*
- X * Trailer pathnames. All must be of the same length.
- X */
- X#define TRAILER "TRAILER!!!" /* Archive trailer (cpio compatible) */
- X#define TRAILZ 11 /* Trailer pathname length (including null) */
- X
- X#include "port.h"
- X
- X
- X#define TAR 1
- X#define CPIO 2
- X#define PAX 3
- X
- X#define AR_READ 0
- X#define AR_WRITE 1
- X#define AR_EXTRACT 2
- X#define AR_APPEND 4
- X
- X/*
- X * Header block on tape.
- X */
- X#define NAMSIZ 100
- X#define PFIXSIZ 155
- X#define TUNMLEN 32
- X#define TGNMLEN 32
- X
- X/* The checksum field is filled with this while the checksum is computed. */
- X#define CHKBLANKS " " /* 8 blanks, no null */
- X
- X/*
- X * Exit codes from the "tar" program
- X */
- X#define EX_SUCCESS 0 /* success! */
- X#define EX_ARGSBAD 1 /* invalid args */
- X#define EX_BADFILE 2 /* invalid filename */
- X#define EX_BADARCH 3 /* bad archive */
- X#define EX_SYSTEM 4 /* system gave unexpected error */
- X
- X#define ROUNDUP(a,b) (((a) % (b)) == 0 ? (a) : ((a) + ((b) - ((a) % (b)))))
- X
- X/*
- X * Mininum value.
- X */
- X#define MIN(a, b) (((a) < (b)) ? (a) : (b))
- X
- X/*
- X * Remove a file or directory.
- X */
- X#define REMOVE(name, asb) \
- X (((asb)->sb_mode & S_IFMT) == S_IFDIR ? rmdir(name) : unlink(name))
- X
- X/*
- X * Cast and reduce to unsigned short.
- X */
- X#define USH(n) (((ushort) (n)) & 0177777)
- X
- X
- X/* Type Definitions */
- X
- X/*
- X * Binary archive header (obsolete).
- X */
- Xtypedef struct {
- X short b_dev; /* Device code */
- X ushort b_ino; /* Inode number */
- X ushort b_mode; /* Type and permissions */
- X ushort b_uid; /* Owner */
- X ushort b_gid; /* Group */
- X short b_nlink; /* Number of links */
- X short b_rdev; /* Real device */
- X ushort b_mtime[2]; /* Modification time (hi/lo) */
- X ushort b_name; /* Length of pathname (with null) */
- X ushort b_size[2]; /* Length of data */
- X} Binary;
- X
- X/*
- X * File status with symbolic links. Kludged to hold symbolic link pathname
- X * within structure.
- X */
- Xtypedef struct {
- X struct stat sb_stat;
- X char sb_link[PATH_MAX + 1];
- X} Stat;
- X
- X#define STAT(name, asb) stat(name, &(asb)->sb_stat)
- X#define FSTAT(fd, asb) fstat(fd, &(asb)->sb_stat)
- X
- X#define sb_dev sb_stat.st_dev
- X#define sb_ino sb_stat.st_ino
- X#define sb_mode sb_stat.st_mode
- X#define sb_nlink sb_stat.st_nlink
- X#define sb_uid sb_stat.st_uid
- X#define sb_gid sb_stat.st_gid
- X#define sb_rdev sb_stat.st_rdev
- X#define sb_size sb_stat.st_size
- X#define sb_atime sb_stat.st_atime
- X#define sb_mtime sb_stat.st_mtime
- X#define sb_ctime sb_stat.st_ctime
- X
- X#ifdef S_IFLNK
- X# define LSTAT(name, asb) lstat(name, &(asb)->sb_stat)
- X# define sb_blksize sb_stat.st_blksize
- X# define sb_blocks sb_stat.st_blocks
- X#else /* S_IFLNK */
- X/*
- X * File status without symbolic links.
- X */
- X# define LSTAT(name, asb) stat(name, &(asb)->sb_stat)
- X#endif /* S_IFLNK */
- X
- X/*
- X * Hard link sources. One or more are chained from each link structure.
- X */
- Xtypedef struct name {
- X struct name *p_forw; /* Forward chain (terminated) */
- X struct name *p_back; /* Backward chain (circular) */
- X char *p_name; /* Pathname to link from */
- X} Path;
- X
- X/*
- X * File linking information. One entry exists for each unique file with with
- X * outstanding hard links.
- X */
- Xtypedef struct link {
- X struct link *l_forw; /* Forward chain (terminated) */
- X struct link *l_back; /* Backward chain (terminated) */
- X dev_t l_dev; /* Device */
- X ino_t l_ino; /* Inode */
- X ushort l_nlink; /* Unresolved link count */
- X OFFSET l_size; /* Length */
- X char *l_name; /* pathname to link from */
- X Path *l_path; /* Pathname which link to l_name */
- X} Link;
- X
- X/*
- X * Structure for ed-style replacement strings (-s option).
- X*/
- Xtypedef struct replstr {
- X regexp *comp; /* compiled regular expression */
- X char *replace; /* replacement string */
- X char print; /* >0 if we are to print replacement */
- X char global; /* >0 if we are to replace globally */
- X struct replstr *next; /* pointer to next record */
- X} Replstr;
- X
- X
- X/*
- X * This has to be included here to insure that all of the type
- X * delcarations are declared for the prototypes.
- X */
- X#include "func.h"
- X
- X
- X#ifndef NO_EXTERN
- X/* Globally Available Identifiers */
- X
- Xextern char *ar_file;
- Xextern char *bufend;
- Xextern char *bufstart;
- Xextern char *bufidx;
- Xextern char *myname;
- Xextern int archivefd;
- Xextern int blocking;
- Xextern uint blocksize;
- Xextern int gid;
- Xextern int head_standard;
- Xextern int ar_interface;
- Xextern int ar_format;
- Xextern int mask;
- Xextern int ttyf;
- Xextern int uid;
- Xextern OFFSET total;
- Xextern short areof;
- Xextern short f_append;
- Xextern short f_create;
- Xextern short f_extract;
- Xextern short f_follow_links;
- Xextern short f_interactive;
- Xextern short f_linksleft;
- Xextern short f_list;
- Xextern short f_modified;
- Xextern short f_verbose;
- Xextern short f_link;
- Xextern short f_owner;
- Xextern short f_access_time;
- Xextern short f_pass;
- Xextern short f_pass;
- Xextern short f_disposition;
- Xextern short f_reverse_match;
- Xextern short f_modification_time;
- Xextern short f_create_dirs;
- Xextern short f_unconditional;
- Xextern short f_newer;
- Xextern time_t now;
- Xextern uint arvolume;
- Xextern int names_from_stdin;
- Xextern Replstr *rplhead;
- Xextern Replstr *rpltail;
- Xextern char **n_argv;
- Xextern int n_argc;
- Xextern FILE *msgfile;
- X#endif /* NO_EXTERN */
- X
- Xextern char *optarg;
- Xextern int optind;
- Xextern int sys_nerr;
- Xextern char *sys_errlist[];
- Xextern int errno;
- X
- X#endif /* _PAX_H */
- END_OF_pax.h
- if test 9317 -ne `wc -c <pax.h`; then
- echo shar: \"pax.h\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f tar.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"tar.c\"
- else
- echo shar: Extracting \"tar.c\" \(7881 characters\)
- sed "s/^X//" >tar.c <<'END_OF_tar.c'
- X/* $Source: /u/mark/src/pax/RCS/tar.c,v $
- X *
- X * $Revision: 1.1 $
- X *
- X * tar.c - tar specific functions for archive handling
- X *
- X * DESCRIPTION
- X *
- X * These routines provide a tar conforming interface to the pax
- X * program.
- X *
- X * AUTHOR
- X *
- X * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- X *
- X * Sponsored by The USENIX Association for public distribution.
- X *
- X * Copyright (c) 1989 Mark H. Colburn.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in all such
- X * forms and that any documentation, advertising materials, and other
- X * materials related to such distribution and use acknowledge that the
- X * software was developed by Mark H. Colburn and sponsored by The
- X * USENIX Association.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * $Log: tar.c,v $
- X * Revision 1.1 88/12/23 18:02:38 mark
- X * Initial revision
- X *
- X */
- X
- X#ifndef lint
- Xstatic char *ident = "$Id: tar.c,v 1.1 88/12/23 18:02:38 mark Rel $";
- Xstatic char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.";
- X#endif /* not lint */
- X
- X/* Headers */
- X
- X#include "pax.h"
- X
- X
- X/* Defines */
- X
- X#define DEF_BLOCKING 20 /* default blocking factor for extract */
- X
- X
- X/* Function Prototypes */
- X
- X#ifdef __STDC__
- X
- Xstatic int taropt(int , char **, char *);
- Xstatic void usage(void);
- X
- X#else /* !__STDC__ */
- X
- Xstatic int taropt();
- Xstatic void usage();
- X
- X#endif /* __STDC__ */
- X
- X
- X/* do_tar - main routine for tar.
- X *
- X * DESCRIPTION
- X *
- X * Provides a tar interface to the PAX program. All tar standard
- X * command line options are supported.
- X *
- X * PARAMETERS
- X *
- X * int argc - argument count (argc from main)
- X * char **argv - argument list (argv from main)
- X *
- X * RETURNS
- X *
- X * zero
- X */
- X
- X#ifdef __STDC__
- X
- Xint do_tar(int argc, char **argv)
- X
- X#else
- X
- Xint do_tar(argc, argv)
- Xint argc; /* argument count (argc from main) */
- Xchar **argv; /* argument list (argv from main) */
- X
- X#endif
- X{
- X int c; /* Option letter */
- X
- X /* Set default option values */
- X names_from_stdin = 0;
- X ar_file = getenv("TAPE"); /* From environment, or */
- X if (ar_file == 0) {
- X ar_file = DEF_AR_FILE; /* From Makefile */
- X }
- X
- X /*
- X * set up the flags to reflect the default pax inteface. Unfortunately
- X * the pax interface has several options which are completely opposite
- X * of the tar and/or cpio interfaces...
- X */
- X f_unconditional = 1;
- X f_modification_time = 1;
- X f_create_dirs = 1;
- X blocking = 0;
- X ar_interface = TAR;
- X ar_format = TAR;
- X msgfile=stdout;
- X
- X /* Parse options */
- X while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
- X switch (c) {
- X case 'b': /* specify blocking factor */
- X /*
- X * FIXME - we should use a conversion routine that does
- X * some kind of reasonable error checking, but...
- X */
- X blocking = atoi(optarg);
- X break;
- X case 'c': /* create a new archive */
- X f_create = 1;
- X break;
- X case 'f': /* specify input/output file */
- X ar_file = optarg;
- X break;
- X case 'h':
- X f_follow_links = 1; /* follow symbolic links */
- X break;
- X case 'l': /* report unresolved links */
- X f_linksleft = 1;
- X break;
- X case 'm': /* don't restore modification times */
- X f_modified = 1;
- X break;
- X case 'o': /* take on user's group rather than
- X * archives */
- X break;
- X case 'r': /* named files are appended to archive */
- X f_append = 1;
- X break;
- X case 't':
- X f_list = 1; /* list files in archive */
- X break;
- X case 'u': /* named files are added to archive */
- X f_newer = 1;
- X break;
- X case 'v': /* verbose mode */
- X f_verbose = 1;
- X break;
- X case 'w': /* user interactive mode */
- X f_disposition = 1;
- X break;
- X case 'x': /* named files are extracted from archive */
- X f_extract = 1;
- X break;
- X case '?':
- X usage();
- X exit(EX_ARGSBAD);
- X }
- X }
- X
- X /* check command line argument sanity */
- X if (f_create + f_extract + f_list + f_append + f_newer != 1) {
- X (void) fprintf(stderr,
- X "%s: you must specify exactly one of the c, t, r, u or x options\n",
- X myname);
- X usage();
- X exit(EX_ARGSBAD);
- X }
- X
- X /* set the blocking factor, if not set by the user */
- X if (blocking == 0) {
- X#ifdef USG
- X if (f_extract || f_list) {
- X blocking = DEF_BLOCKING;
- X fprintf(stderr, "Tar: blocksize = %d\n", blocking);
- X } else {
- X blocking = 1;
- X }
- X#else /* !USG */
- X blocking = 20;
- X#endif /* USG */
- X }
- X blocksize = blocking * BLOCKSIZE;
- X buf_allocate((OFFSET) blocksize);
- X
- X if (f_create) {
- X open_archive(AR_WRITE);
- X create_archive(); /* create the archive */
- X } else if (f_extract) {
- X open_archive(AR_READ);
- X read_archive(); /* extract files from archive */
- X } else if (f_list) {
- X open_archive(AR_READ);
- X read_archive(); /* read and list contents of archive */
- X } else if (f_append) {
- X open_archive(AR_APPEND);
- X append_archive(); /* append files to archive */
- X }
- X
- X if (f_linksleft) {
- X linkleft(); /* report any unresolved links */
- X }
- X
- X return (0);
- X}
- X
- X
- X/* taropt - tar specific getopt
- X *
- X * DESCRIPTION
- X *
- X * Plug-compatible replacement for getopt() for parsing tar-like
- X * arguments. If the first argument begins with "-", it uses getopt;
- X * otherwise, it uses the old rules used by tar, dump, and ps.
- X *
- X * PARAMETERS
- X *
- X * int argc - argument count (argc from main)
- X * char **argv - argument list (argv from main)
- X * char *optstring - sring which describes allowable options
- X *
- X * RETURNS
- X *
- X * Returns the next option character in the option string(s). If the
- X * option requires an argument and an argument was given, the argument
- X * is pointed to by "optarg". If no option character was found,
- X * returns an EOF.
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xstatic int taropt(int argc, char **argv, char *optstring)
- X
- X#else
- X
- Xstatic int taropt(argc, argv, optstring)
- Xint argc;
- Xchar **argv;
- Xchar *optstring;
- X
- X#endif
- X{
- X extern char *optarg; /* Points to next arg */
- X extern int optind; /* Global argv index */
- X static char *key; /* Points to next keyletter */
- X static char use_getopt; /* !=0 if argv[1][0] was '-' */
- X char c;
- X char *place;
- X
- X optarg = NULL;
- X
- X if (key == NULL) { /* First time */
- X if (argc < 2)
- X return EOF;
- X key = argv[1];
- X if (*key == '-')
- X use_getopt++;
- X else
- X optind = 2;
- X }
- X if (use_getopt) {
- X return getopt(argc, argv, optstring);
- X }
- X
- X c = *key++;
- X if (c == '\0') {
- X key--;
- X return EOF;
- X }
- X place = strchr(optstring, c);
- X
- X if (place == NULL || c == ':') {
- X fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
- X return ('?');
- X }
- X place++;
- X if (*place == ':') {
- X if (optind < argc) {
- X optarg = argv[optind];
- X optind++;
- X } else {
- X fprintf(stderr, "%s: %c argument missing\n",
- X argv[0], c);
- X return ('?');
- X }
- X }
- X return (c);
- X}
- X
- X
- X/* usage - print a helpful message and exit
- X *
- X * DESCRIPTION
- X *
- X * Usage prints out the usage message for the TAR interface and then
- X * exits with a non-zero termination status. This is used when a user
- X * has provided non-existant or incompatible command line arguments.
- X *
- X * RETURNS
- X *
- X * Returns an exit status of 1 to the parent process.
- X *
- X */
- X
- X#ifdef __STDC__
- X
- Xstatic void usage(void)
- X
- X#else
- X
- Xstatic void usage()
- X
- X#endif
- X{
- X fprintf(stderr, "\
- XUsage: %s -c[bfvw] device block filename..\n", myname);
- X fprintf(stderr, "\
- X %s -r[bvw] device block [filename...]\n", myname);
- X fprintf(stderr, "\
- X %s -t[vf] device\n", myname);
- X fprintf(stderr, "\
- X %s -u[bvw] device block [filename...]\n", myname);
- X fprintf(stderr, "\
- X %s -x[flmovw] device [filename...]\n", myname);
- X exit(1);
- X}
- END_OF_tar.c
- if test 7881 -ne `wc -c <tar.c`; then
- echo shar: \"tar.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 3 \(of 6\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-